package com.hospital.register.order.utils;

import com.github.wxpay.sdk.WXPayConfig;
import com.github.wxpay.sdk.WXPayConstants;
import com.github.wxpay.sdk.WXPayUtil;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.SSLContext;
import java.io.File;
import java.io.InputStream;
import java.security.KeyStore;
import java.util.HashMap;
import java.util.Map;

/**
 * 微信支付HTTP客户端
 * 使用微信官方SDK的标准实现，解决SSL兼容性问题
 */
public class WxpayHttpClient {
    
    private static final Logger logger = LoggerFactory.getLogger(WxpayHttpClient.class);
    
    /**
     * 微信支付配置类
     */
    private static class WxpayConfig implements WXPayConfig {
        private String appId;
        private String mchId;
        private String key;
        private String certPath;
        private String certPassword;
        
        public WxpayConfig(String appId, String mchId, String key, String certPath, String certPassword) {
            this.appId = appId;
            this.mchId = mchId;
            this.key = key;
            this.certPath = certPath;
            this.certPassword = certPassword;
        }
        
        @Override
        public String getAppID() {
            return appId;
        }
        
        @Override
        public String getMchID() {
            return mchId;
        }
        
        @Override
        public String getKey() {
            return key;
        }
        
        @Override
        public InputStream getCertStream() {
            try {
                File certFile = new File(certPath);
                if (certFile.exists()) {
                    return new java.io.FileInputStream(certFile);
                }
            } catch (Exception e) {
                logger.error("获取证书流失败", e);
            }
            return null;
        }
        
        public String getCertPassword() {
            return certPassword;
        }
        
        @Override
        public int getHttpConnectTimeoutMs() {
            return 8000;
        }
        
        @Override
        public int getHttpReadTimeoutMs() {
            return 10000;
        }
    }
    
    /**
     * 使用微信官方SDK发起退款请求
     * 
     * @param params 请求参数
     * @return 响应结果
     * @throws Exception
     */
    public static Map<String, String> refund(Map<String, String> params) throws Exception {
        // 创建配置
        WxpayConfig config = new WxpayConfig(
            WXPayAccountConstants.APPID,
            WXPayAccountConstants.PARTNER,
            WXPayAccountConstants.PARTNERKEY,
            WXPayAccountConstants.CERT,
            WXPayAccountConstants.PARTNER
        );
        
        // 填充必要参数
        params.put("appid", config.getAppID());
        params.put("mch_id", config.getMchID());
        params.put("nonce_str", WXPayUtil.generateNonceStr());
        
        // 生成签名
        String signedXml = WXPayUtil.generateSignedXml(params, config.getKey());
        
        // 创建SSL上下文
        SSLContext sslContext = createSSLContext(config);
        
        // 创建HTTP客户端
        try (CloseableHttpClient httpClient = HttpClients.custom()
                .setSSLSocketFactory(new SSLConnectionSocketFactory(
                    sslContext,
                    new String[]{"TLSv1", "TLSv1.1", "TLSv1.2"},
                    null,
                    SSLConnectionSocketFactory.getDefaultHostnameVerifier()
                ))
                .build()) {
            
            // 创建请求
            HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/secapi/pay/refund");
            httpPost.setEntity(new org.apache.http.entity.StringEntity(signedXml, "UTF-8"));
            
            // 执行请求
            try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
                HttpEntity entity = response.getEntity();
                String result = EntityUtils.toString(entity, "UTF-8");
                
                // 只记录关键信息
                int statusCode = response.getStatusLine().getStatusCode();
                if (statusCode != 200) {
                    logger.warn("退款请求响应状态码: {}", statusCode);
                }
                
                // 解析响应
                return WXPayUtil.xmlToMap(result);
            }
        }
    }
    
    /**
     * 创建SSL上下文
     */
    private static SSLContext createSSLContext(WxpayConfig config) throws Exception {
        try (InputStream certStream = config.getCertStream()) {
            if (certStream == null) {
                throw new Exception("证书文件不存在或无法读取: " + WXPayAccountConstants.CERT);
            }
            
            // 加载证书
            KeyStore keyStore = KeyStore.getInstance("PKCS12");
            keyStore.load(certStream, config.getCertPassword().toCharArray());
            
            // 创建SSL上下文
            SSLContext sslContext = SSLContexts.custom()
                    .loadKeyMaterial(keyStore, config.getCertPassword().toCharArray())
                    .build();
            
            return sslContext;
        }
    }
    
    /**
     * 测试证书连接
     */
    public static boolean testCertConnection() {
        try {
            Map<String, String> testParams = new HashMap<>();
            testParams.put("out_trade_no", "test");
            testParams.put("out_refund_no", "test_refund");
            testParams.put("total_fee", "1");
            testParams.put("refund_fee", "1");
            
            // 这里只是测试SSL连接，实际会失败，但能验证证书是否正确
            refund(testParams);
            
        } catch (Exception e) {
            // 如果是业务错误（如订单不存在），说明SSL连接成功
            if (e.getMessage() != null && 
                (e.getMessage().contains("订单") || 
                 e.getMessage().contains("OUT_TRADE_NO") ||
                 e.getMessage().contains("XML"))) {
                logger.info("证书连接测试成功 - SSL握手正常");
                return true;
            }
            
            // 如果是SSL错误，说明证书有问题
            logger.error("证书连接测试失败: {}", e.getMessage());
            return false;
        }
        
        return false;
    }
}
